 PAG
*-------------------------------------------------
*            SEG0
*-------------------------------------------------

**************************************************************************
*------------------ DO NOT CHANGE CODE IN THIS SECTION  -----------------*
*------------------ so entry points can be published. -------------------*
**************************************************************************

]segnum = #$0000 ;current segment number

 ORG $E0C800 ;2K SLOT

* THE FOLLOWING IS RUN FROM THE CARD SLOT SPACE.
* The DDT16 must be in slots 4,5,6 or 7.

* THIS IS FIRST INSTRUCTION IN EPROM

Start1 PHP
 SEC
 BRA StayIn

*-------------------------------------
* --- Alternate entry point ---
* Start here if you want the DDT card to do an RTS after it is initialized.
* The contents of the Accumulator determine the return condition as follows:
* A = 02 The button & BRKs are not enabled, writing to DDT is enabled,
*        accessing the vectors $FFE8-$FFFF is OK.
* A = 03 The button is the only way back into the DDT. Accessing the vectors
*        is OK. The DDT is write protected.
* A = XX The button & BRKs are enabled, writing to DDT is enabled, accessing
*        the vectors will disable the Apples ROM in the $FFxx addresses.
* If entered in emulation mode (E=1) we do an RTS
* Else we do an RTL

Start2 PHP
 CLC
 BRA StayIn

*---------------------------------------------------
* --- Alternate entry point ---
*
* Warm reentry. Entering here preserves user's breakpoints and system settings.

WarmEntr
 BRA CmdDoRTS

* come here to restore user's status incase interrupts are pending
SlotPLP EQU *-1 ;equate for RTS
 PLP ;restore status
 RTL  ;go to user's return address

 HEX A2 ;$A2 is device signature

**************************************************************************
*------------------ DON'T CHANGE ANYTHING ABOVE THIS POINT --------------*
*------------------ so entry points can be published. -------------------*
**************************************************************************

StayIn MEMORY8
 CLD
 STAL $E0CFFF ;get 2K space
 STAL ACC ; save Acc
 ROR ;SET MSB WITH CARRY
 STAL Strt2Flg ;BIT 7=0 DO AN RTS AFTER INITIALIZATION

 CLC
 XCE ;native mode
* Save User's return address from stack
 MEMORY16
 LDA $02,S ;GET RETURN ADDRESS
 STAL RET_ADD ;SAVE for "QU" command
 MEMORY8

* Put next 3 lines here from SAVEREG so COMDJS did not change DBR
 PHB
 PLA
 STAL DBR ;SAVE DATA BANK REG.
 XCE  ;restore user's E flag so its saved in SAVEREG

 PLP ;retrieve status
 JSR SAVEREG ;SAVE REGISTERS & SWITCHES, $E0 TO DBR
* Returns with MX8 & stack in work stack area.

* Put next 3 lines here from SAVEREG so COMDJS did not change PBR
 PHK
 PLA
 STA PBR ;set to user's PBR

* DETERMINE SLOT NUMBER
 JSR PUTSLOT ;PUT SLOT NUMBER ON STACK
 LDA $00,S
 STA SLOTCN ;SAVE SLOTCN
 AND #$0F ;MAKE SLOT0N
 ASL
 ASL
 ASL
 ASL
 STA SLOTN0 ;SAVE SLOT NUMBER n0
 TAX

* Use Misc. Tools to find the location of the BRK Variables
 MX16
 PHA  ;space for result
 PHA  ;
 PEA #$0009 ;parameter for BRK VAR
 LDX #$1603 ;misc tools #16
 JSL $E10000 ;make tool call

* Go to the end of the slot space to finish the startup to leave room above
* $Cn7F for the routines that need it
 BRA STARTUP2
 mx %11

*------------------------------------------
* RETURN POINT FROM COMDDO USER SUBROUTINE
**** ALSO USED BY WARMENTR ****

CMDDORTS
 STAL $E0CFFF
 SEI  ;disable interrupts
 JSR RTSREST ;SAVE REGISTERS, SET NATIVE MODE & MX8
 SEC
 ROR INITFLAG ;INDICATE USER MAY HAVE MESSED WITH SCREEN
 JMP CMDOCONT ;continue in 2K slot

*======================================================================
*       DDT  INTERRUPT  HANDLER
*
* All interrupts vectored here from C0INT code in I/O space
*

SLOTINT STAL $E0CFFF ;2K off (must be before $Cn7F)
 JMP INTSTUFF ;DO INTERRUPT HOUSE KEEPING STUFF

* Return here from I/O routines
IORETRN XCE  ;save Carry
 CLC ;restore native mode
 XCE

** Enable DDT's 2K slot
DDTENAB STA $CFFF ;Disable all 2K slots
 RTS ;Only our 2K slot is active

* Return from I/O routines to card slot space
SLOTRTS EQU *
 STAL $E0CFFF ;DISABLE 2K
* THIS POINT MUST BE BEFORE $CN7F
 ERR *-1/$E0C87F

 PLX ;restore X that was saved in LDA/STAINDY

* Restore memory state switches
 STA WRITMAIN ;DEFAULT TO MAIN
 STA READMAIN
:OFF JSR EXCHZPAG ;EXCHANGE ZERO PAGE LOCATIONS
 CLD
 CMP #0 ;SET CONDITION CODES
 RTS

*----------------------------------------
* Continue break handler

BREAK MEMORY16
 LDA PCLO ;correct for the way the BRK inst works
 DEC
 DEC
 STA PCLO
 MEMORY8

 JSR TRANSFR0 ;SET PBR IF EMULATION MODE, SET INITFLAG
 DFB SETPBRC ;code
 STA PASSFLG ;CONTINUE WITH GO AFTER TRACING
 JMP LOOKBRK ; THRU BRK

 MX %11

****************************************
* THIS POINT MUST BE AFTER $Cn7F

**** ERR *-1/$E0C880
**** DS $E0C880-*,$FF
 ERR $E0C87F/*

*----------------------------------------
* Pascal 1.1 slot interface
*
* Call the firmware routine specified by the low byte of the Acc in the
* Pascal V1.1 compatible device in slot 1 or 2. Enter with X=$C1 or $C2, Y=$n0,
* Acc low byte = offset to Pascal entry point offset.
* Acc hi byte = character to write if writing or status request code.

TOPASCAL EQU *-1 ;EQU for RTS
 PHY ;save $n0
 TAY ;offset to Pascal firmware routine
 BIT $CFFF ;disable 2K ROMS
 CPX #$C1 ;slot #1 ?
 BNE :SLOT2 ;if no
 BIT $C100 ;enable slot 1
 LDA $C100,Y ;Pascal firmware offset
 BRA :CONT
:SLOT2 BIT $C200 ;enable slot 2
 LDA $C200,Y ;Pascal firmware offset
:CONT DEC ;offset - 1
 PLY ;restore Y
 SEC
 XCE  ;8 bit mode for Pascal 1.1 calls
 PER IORETRN-1 ;return address in our slot space
 PHX ;$C1 or $C2
 PHA ;low byte of firmware offset -1
 XBA ;character to send if writing or request code
 RTS ;simulate JSR to Pascal firmware

*-----------------------------------------------------------
* continuation of startup
 mx %00

STARTUP2
 PLA  ;get low word of BRK VAR vector
 STA BRKSTUF ;save in DDT RAM
 PLA  ;get hi word
 MX8
 STA BRKSTUF+2

* Clear LS109 bottom to allow segment changes.
 LDA #%11111110 ;CB2 HI, CB1 POS EDGE, CA2 HI, CA1 NEG EDGE
 STA VIAPCR ;Set up VIA

* Initialize DDT interrupt vector buffers
* Init RAM & VIA, display windows & copyright notice
 JSR TRANSFR0 ;INITIALIZE RAM VECTORS & VIA
 DFB INITRAMVC ;CODE

* Display program version number & date, set VIA condition
* Set condition code C as follows:
* C = 1 = enter DDT
* C = 0 = return to user after init

 JSR TRANSFR0
 DFB DISVERSC ;code

 BCC :NOENTER ;Do not Enter DDT
 JMP GETCOM0 ;Enter DDT

**************************************************
* LEAVE DDT
**************************************************

* Restore stack & DBR
:NOENTER
 INDEX16
 LDX STACK ;GET USER'S STACK
 TXS ;RESTORE
 INDEX8
 XBA ;SAVE LOW BYTE OF ACC
 LDA DBR ;GET USER'S DBR
 PHA
 PLB ;restore DBR
 XBA ;RESTORE LOW BYTE OF ACC
 STA VIAPCR ;Set return condition
 BIT EMULATE ;what mode was user in?
 BMI :DORTS ;IF emulation mode
 RTL ;RETURN BACK TO USER WITH DDT INITIALIZED
:DORTS RTS ;user was in emulation mode so do RTS

*-------------------------------------------------
*  NMICONT
*
* Setting InitFlag causes the text page & switches to be saved
* by the DDT output routines if invisible mode is on.
NMICONT JMP NMIVEC2 ;jump to the NMI handler in 2K space

*-------------------------------------------------
* USERINT = The interrupt was not from DDT so go to User's interrupt handler
USERINT JMP TOC0N0IO

*** This point must be before $C8FD
 LST ON
 ERR *-1/$E0C8FD

 DS $E0C8FD-*,$FF ;fill with $FF

* Version number of DDT16 used by Init
 DW VERSION

 HEX 01 ;don't change speed register
 do nolist
 LST OFF
 fin

******************************************************************************
*                     STARTING SEGMENT 0 OF 2K SLOT.
*
* !!!!!! WARNING !!!!!!!
* Bible verse follows. Don't read at your own risk.
*
******************************************************************************

 ASC "For God so loved the world, that he gave his only begotten "
 ASC "Son, that whosoever believeth in him should not perish, "
 ASC "but have everlasting life. (St. John 3:16)"

 ERR *-1/$E0CA00
*******************************************
* MAKE SURE THIS POINT IS $CA00 OR HIGHER *
*******************************************

 DS $E0CA00-*,$FF

*---------------------------------------------------
*       NMIVEC (must start in segment zero)

NMIVEC2
 JSR TRANSFR0 ;SET PBR IF EMULATION MODE, SET INITFLAG
 DFB SETPBRC ;code

 LDA VIAIFR ;GET INTERRUPT FLAG REG.
 AND IERBUFF ;TEST ONLY THOSE BITS THAT ARE ENABLED
 LSR
 LSR
 BCS COMMDRCL ;IF BUTTON

 BIT ETFLAG ;Was NMI caused by ET?
 BMI CONTNMI ;If yes

 BIT TRACFLAG ;Was NMI caused by Trace?
 BMI CONTNMI ;if yes

* NMI was caused by Hard Break
 BIT HALT_ALL ;IF SET HALT IN ALL BANKS
 BMI HARDSTP ;STOP
 LDA DBR
 CMP HARDPBR ;STOP IN THIS BANK?
 BEQ HARDSTP ;IF YES
 LDA PBR
 CMP HARDPBR ;STOP IN THIS BANK?
 BEQ HARDSTP ;IF YES
DOEXEC JMP EXECUTE ;don't stop in this bank

HARDSTP JSR TRANSFR0 ;DISPLAY "HARD BREAK"
 DFB DISHARDC ;CODE

COMMDRCL JMP COMDDR

CONTNMI JMP (ENABLTVC) ;GO TO THE TRACE VECTOR LOCATION

*-------------------------------------------------
* Come here if NMI caused by ET or Trace

ETVECTOR JSR TRANSFR0 ;CONTINUE IN different segment
 DFB ETVCONTC ;code
 BIT TRACFLAG ;was NMI caused by Trace?
 BPL :NOTRAC ;if no
 JMP NMITRC ;if yes
:NOTRAC JMP GETCOM0

*-------------------------------------------------
* Disable all interrupts, put /INIT low

CMDOCONT LDA #%01111111 ;DISABLE ALL INTERRUPTS
 STA VIAIER ;ALSO CLEARS BIT 7 OF VIAIFR
 LDA VIAPCR ;ENTER HERE TO PUT /INIT LOW
 ORA #%11101110 ;REMOVE INVISIBILITY (CA2 HI) & don't replace
 STA VIAPCR ;Apple's vectors, allow switching segments (CB2 hi)

 JSR TRANSFR0 ;ZPAGESAVE, SETMSTAT, DISPON
 DFB WARMINITC ;code
 JMP GETCOM0

********************************
*  COMDTR
*  Performs same as COMDST but does not display registers.
********************************

COMDTR EQU *
 PHP
 SEC
 ROR STFLAG ; set ST flag to not display registers
 PLP
 BRA TRCONT

********************************
*  COMDEX
********************************

COMDEX STA EFLAG

********************************
*  COMDST
********************************

COMDST EQU *
 STZ STFLAG ; set ST flag to display registers

TRCONT BEQ TRACE1 ;NO, DO ONE TRACE
ECOMMAND
 JSR TRANSFR0 ;READ NUMBER
 DFB CHKREADC ;code
 BCC LOADT ;IF VALID
BADPAR0 LDA #BADPAR ;ERROR NUMBER

ERREXIT0
 BIT $CF00 ;ENABLE EXT RAM
 JSR TRANSFR0 ;INVALID COMMAND
 DFB ERRBEEPC ;CODE BYTE
 JMP GETCOM0

LOADT MEMORY16
 LDA LETTER1
 STA TCOUNT ;LOAD TRACE COUNT
 MEMORY8
 BRA STEP1 ;LOOK FOR BREAK

********************************
*  COMDER
********************************

COMDER STA RTSFLAG

S_TRACE1 = ]segnum ;segment number of command
TRACE1 STZ TCOUNT+1
 LDX #1
 STX TCOUNT ;SET TCOUNT FOR ONE TRACE

*---------------------------------------------
* Do 1 instruction, even our REAL break, don't stop even if break count
* reaches zero, then go to the NMITRC vector location.
* This allows continuing through a break with TR, EX & ER

S_STEP1 = ]segnum ;segment number of this routine
STEP1 SEC
 BCS LTRACEVC

*-----------------------------
* Do 1 instruction, even our real break, but
* stop if the break count reaches zero, else goto NMITRC.

LOOKBRK CLC

S_LTRACE = ]segnum ;segment number of this command
LTRACEVC
 ROR STOPBRK ;<$80=STOP IF TOGOFLG=0,>$7F=DON'T STOP
 JSR TRANSFR0 ;IF OUR BRK, DEC TOGO
 DFB DECTGPCC ;code
 BMI TRACEN ;NOT BREAK OR NOT OURS
 PHP ;SAVE STATUS

 SEC
 ROR BRKWFLG ;NEED TO UPDATE THE BRK WINDOW

 BIT STOPBRK ;STOP IF TOGOFLG = 0 ?
 BMI :CONT ;IF > $7F THEN DON'T STOP

 LDA TOGOFLG ;TOGO = 0 ?
 BNE :CONT ;IF NO
 PLA
 JMP TRACEND ;STOP & DISPLAY REGISTERS
:CONT PLP
 BNE TRACEN ;IMPLIED BRK

* Disable HARD break so the soft break is not lost
 LDA #$02
 TRB IERBUFF ;disable button interrupt

 JSR TRANSFR0 ;REPLACE THE 00 WITH ORIGINAL INSTRUCTION BYTE
 DFB REPLACEC ;CODE BYTE
 SEC
 ROR BRKTRFLG ;indicate we are tracing through one of our breaks

*-------------------------------------------------
* Trace N instructions of the target program

TRACEN

* Check realtime & program only windows

 BIT REALTIME ;ARE REALTIME RANGES SET ?
 BMI :CHKPWIN ;IF YES CHECK PROT WINDOW
 BIT PROGONLY ;ARE PROGRAM ONLY RANGES SET ?
 BPL :NOPR ;IF NO

* If YES, K/PC must be inside program only range to be executed

:CHKPWIN LDX #30
:CHECK LDA PROTADR,X ;GET PROT TYPE
 CMP #"T" ;CODE TRACE RANGE ?
 BNE :CHKP ;IF NO
 JSR TRANSFR0 ;IN RANGE ?
 DFB CHKRANGC ;code
 BCC :NEXT ;IF NO
 STZ COMRTFLG ;COMDRT NOT active (7=0), FROM PROTWIND (6=0)
 JMP NMICOMRT ;IF YES, RUN SUBROUTINE IN REALTIME
:CHKP CMP #"P" ;PROGRAM ONLY RANGE ?
 BNE :NEXT
 JSR TRANSFR0 ;IN RANGE ?
 DFB CHKRANGC ;code
 BCS :NOPR ;IF YES, CONTINUE TRACE
:NEXT SEC
 TXA
 SBC #6 ;NEXT TYPE
 TAX
 BPL :CHECK

* OUT OF RANGES. If PROG only flag is set and we are here, we must be
* outside PROG only window, so stop tracing & indicate outside PROG range.

 BIT PROGONLY ;ARE PROGRAM ONLY RANGES SET ?
 BPL :NOPR ;IF NO
 JSR TRANSFR0 ;OUTSIDE PROG RANGE
 DFB OUTPRGRC ;code
 BCC :NOPR ;OUR SLOT I/O SPACE IS OK
 JMP COMDDR

:NOPR
* LDA MSTATE
* STA OLDMSTAT ;SAVE OLD MSTATE

 JSR LDAPBRIY ;GET BYTE AT PBR/PC
 STA USEROPCD ;SAVE USER'S OPCODE
 BNE :NOTBRK ;IF NOT BRK

* Is BRK out realtime BRK ?

 BIT RTBRKFLG
 BPL :HALTBRK ;if not realtime
 INDEX16 ;16 BIT
 LDX STACK ;IS THIS OUR REALTIME BRK
 CPX RTSTACK ;STACK AT PRE REALTIME LOCAL ?
 INDEX8 ;8 BIT
 BNE :HALTBRK ;if not, halt
 JSR TRANSFR0 ;RESTORE CHANGED STUFF
 DFB RESTRTC ;code
 BVC :RTWIND ;IF RESULT OF T range
:HALTBRK
 JMP COMDDR ;END COMDRT
:RTWIND JMP NMITRC ;CONTINUE WITH WHATEVER

:NOTBRK INDEX16
 LDX STACK
 STX RTSTACK ;save current stack for possible use by realtime
 INDEX8
 LDA #$80
 TSB TFLAG ;TFLAG, enable T: mode
 TSB TRACFLAG ;trace is active

 JSR TRANSFR0
 DFB TRSETVIAC ;set VIA for trace

 JMP EXECUTE ;RESTORE REGISTERS AND RUN PROGRAM.

*----------------------------------------
* Come here after tracing 1 instruction to continue COMDRT

NMICOMRT JSR TRANSFR0 ;SET UP FOR REALTIME & GOTO EXECUTE
 DFB SETUPRTC ;code

* Returns if an error occurs.
 LDY #1 ;position error message
 BVC :NOROM
 LDA #BADRT ;JSL not allowed with RT or T range in 8 bit mode
 BRA :TOERR

* A BRK could not be placed at the instruction pointed to by the
* stacked return address.
:NOROM LDA #WRITFAIL ;Not able to write to desired location
:TOERR JMP ERREXIT0

*-------------------------------------------------
* If TRace causes an NMI the NMI handler routine sends
* the program to NMITRC.

BRKTRC LDA #$02
 TSB IERBUFF ;reenable button interrupt
 LDA LETTER3 ;ADDRESS WAS PUT IN LETTER 3,2,1
 STA DBRDDT ;BY VALIDPC OR DECTGPC
 MEMORY16
 LDA LETTER1
 STA LOWADD
 MEMORY8
 LDY #0
 TYA
 JSR STAINDY ;PUT BREAK BACK IN
 INC POINT ;POINT TO OLD BRK INFO
 INC REALBRK ;REAL BRK COUNT
 RTS

*-------------------------------------------------
* Continue after NMI from Trace

NMITRC STZ TRACFLAG ;clear Trace active flag
 LDA #$80
 TRB BRKTRFLG ;are we tracing our real break?
 BEQ :NOBRK ;if no
 JSR BRKTRC ;if yes

:NOBRK LDA #$80
 TRB GOFLAG ;was command GO?
 BEQ :NOGO ;if no
 JMP EXECUTE ;if yes

:NOGO TRB COMRTFLG ;was COMDRT active?
 BNE NMICOMRT ;if yes

 LDA EFLAG ;WAS COMMAND EX ?
 BMI EXCONT ;IF YES

 BIT RTSFLAG ;ARE WE LOOKING FOR AN RTS
 BPL :CHKPAS ;IF NO
 JSR LDAPCIY ;GET INTRUCTION BYTE
 CMP #$6B ;is it an RTL
 BEQ :STOPEX ;if yes
 CMP #$60 ;is it an RTS
 BNE CHKCTRLS ;if no
:STOPEX JMP COMDDR ;IF YES STOP LOOKING AND DISPLAY REGISTERS.

* Did we get here from the break handler ?

:CHKPAS BIT PASSFLG
 BPL :CHKTS ;IF NO
 STZ PASSFLG ;RESET
 JMP EXECUTE ;CONTINUE

:CHKTS BIT TSFLAG ;IS THIS COMDTS ?
 BMI DOSUB ;IF YES

 JSR TRANSFR0 ;DISPLAY REG'S FROM RAM & DISASSEM INSTRUCTION
 DFB INITDISRC ;CODE BYTE

* Decrement Tcount

SKIPREG MEMORY16
 DEC TCOUNT ;DECREMENT BY 1
 MEMORY8
 BNE MORETR ;MORE TRACING

TRACEND BIT PASSFLG ;DID WE GET HERE FROM A BRK?
 BMI COMDDR ;IF YES
 BIT EFLAG ;ARE WE DOING EXECUTE N INSTRUCTIONS?
 BPL LEAVTRC ;IF NO

**********************************
*  COMDDR
**********************************

COMDDR STZ STFLAG ; enable display of registers
 JSR TRANSFR0 ;IF YES DISPLAY REGISTERS
 DFB INITDISRC ;CODE BYTE
LEAVTRC STZ EFLAG
 STZ RTSFLAG
 STZ PASSFLG
 JMP GETCOM0 ;TRACE FINISHED

EXCONT CMP #"0" ; EXECUTE PROGRAM UNTIL CTRL-X
 BNE SKIPREG ; EX COMMAND SO DON'T DISPLAY REGISTERS
MORETR

* Check for ctrl-S & esc

CHKCTRLS BIT IOMODE ;I/O TO SERIAL?
 BMI :SERUSED ;IF YES
 LDA KBD ;READ KEYBOARD
 BPL TOTRACEN ;NO KEYPRESSED SO CONTINUE
 CMP KEY ;IS IT STOP COMMAND
 BNE TOTRACEN ;NO, CONTINUE
 BIT KBDSTRB ;YES, CLEAR KBD
:WAITKEY LDA KBD ;READ KEYBOARD
 BPL :WAITKEY ;WAIT FOR KEYPRESS
 BMI CHKESC ;KEY PRESSED

* USE serial I/O
:SERUSED LDA #$1 ;request code, 'is input ready?'
 JSR TRANSFR0 ;get serial I/O status
 DFB STATPASCC ;code
 BCC TOTRACEN ;no keypress
 JSR TRANSFR0 ;get serial data
 DFB INPASCALC ;code
 CMP KEY ;IS IT stop command?
 BNE CHKESC ;IF NO
WAITSSC JSR TRANSFR0 ;WAIT FOR KEYPRESS
 DFB RECEIVEC ;code

* Was it esc ?

CHKESC CMP #ESC ;IS IT ESC
 BEQ COMDDR ;YES, STOP TRACE
TOTRACEN JMP LOOKBRK ;NO, CONTINUE

*-------------------------------------------------
* Do the user's subroutine and stop if carry is set.

DOSUB LDA STATUS
 ORA #$04 ;set I flag
 PHA
 MX16
 LDX XREG ;RESTORE REGISTERS
 LDY YREG
 LDA ACC
 PLP ;RESTORE STATUS
 JSL USERSUB ;DO USER SUB

* Come here after user's RTL

USERRTS CLD ;IN CASE SET BY USER
 MX8
 BCC CHKCTRLS ;CONTINUE
 LSR TSFLAG ;CLEAR TSFLAG
 BRA COMDDR ;STOP

USERSUB JMP [SUBTRACE]

*-------------------------------------------------
*  LOCAL SUBROUTINES
*-------------------------------------------------

 MX %11

*---------------------------------------------------
***** STAINDY AND LDAINDY MAY NOT BE USED TO CHANGE
***** DISPLAY OR OTHER SOFT SWITCHES.

LDAPBRIY ;LOAD BYTE AT PBR/PC
 LDA PBR
 STA DBRDDT ;BANK TO ACCESS
LDAPCIY MEMORY16
 LDA PCLO ;LOAD PC
 STA LOWADD
 MEMORY8
 LDY #0

*---------------------------------
* LDA LOWADD,X FROM CARD I/O SPACE

LDAINDY LDA #$BF ;LDAL OP,X OPCODE
 BRA CARDSLT1

*---------------------------------
* STA LOWADD,X FROM CARD I/O SPACE

STAINDY STA STAISAV ;save value to store
 LDA #$9F ;STAL OP,X OPCODE

CARDSLT1 PHX ;SAVE, restored by SLOTRTS
 PHY ;save
 XBA ;save opcode

 LDA CXSTATUS ;get CXROM status
 ROL ;set Carry with CXSTATUS		

 PHD ;save

 LDA DBRDDT ;data bank to access
 TCD ;D = opcode, DBR

 LDX SLOTN0
 INDEX16
 LDY LOWADD ;address to access

******************************************
* !!! CAUTION !!! SEGMENT DEPENDENT CODE *
******************************************
 LDA #%10000000 ;RAM8, ROM0
 STA SEGMBASE,X

 LDA #$07 ;default to CX on
 BCS :CXON ;if yes
 LDA #$06
:CXON STA IOCX8

 STY IOLADRS ;address to access
 TDC
 STA IODBR ;bank to access
 XBA
 STA IOOPCD ;put LDA/STA opcode
 INDEX8

******************************************
* !!! CAUTION !!! SEGMENT DEPENDENT CODE *
******************************************
 STZ SEGMBASE,X ;RAM0, ROM0

 PLD
 PLY ;restore
 TYX ;routine now does STA,X

 LDA STAISAV ;for STA this restores value to store
 JSR AX2S1_B ;Acc & X to SEG1 RAM, set CX & slot switch

 JSR EXCHZPAG ;Exchange ZERO page locations
 LDX SLOTN0 ;slot number n0
 CLC ;keep in emulation mode
 JMP TOC0N0IO ;go to I/O routines in C0n0 space

*--------------------------------
*  EXECUTE
*  Go run the user's code at (PBR)/PCHI PCLO
* !!!! WARNING !!!! Stack must NOT be in DDTRAM when AX2S1_A is executed
*--------------------------------

EXECUTE

* Restore the text page & Replace the interrupt vectors if VECTORS=0
* Setup SEG7 I/O routine
 JSR TRANSFR0
 DFB RESTSTUFC ;code

 JSR AX2S1_A ;Save ACC & XREG to SEG1 RAM

* Restore the user's stack
 INDEX16
 LDX #DDTSTACK
 TXS ;PUT STACK IN DDT RAM
 JSR STACKRES ;RESTORE USER'S STACK
* stackres returns with MX16
 MX %00

* Restore part of the registers
 MEMORY8
 LDX DREG ;GET DIRECT REG.
 PHX
 PLD ;RESTORE DIRECT REG.
 LDA DBR ;DATA BANK REGISTER
 PHA ;PULLED BELOW
 LDY YREG ;Restore 8 or 16 bit Y

* Initialize VIA
 LDA #%11011110 ;CB2 LOW, CB1 POS EDGE, CA2 HI, CA1 NEG EDGE
 STA VIAPCR ;REPLACE APPLE'S VECTORS

* Carry flag remains unchanged until used.
 LDA EMULATE
 ROL ;SET CARRY WITH EMULATION FLAG

* Setup ACC for segment change
 LDA #0
 XBA ;make upper byte 0
 LDA SLOTN0

* Finish restoring registers
 LDX STACK ;GET USER'S STACK
 PLB ;RESTORE USER'S DATA BANK
 TXS ;RESTORE USER'S STACK

 TAX ;setup with slotn0 above

 XCE ;restore user's mode so stack works the same
 LDAL PBR
 BNE :DOPBR ;native mode or 8 bit code in non zero bank
 LDAL EMULATE ;was PBR really 0 in native mode?
 BMI :EMUL ;skip PBR if emulation mode
 LDA #0 ;native mode PBR was 0
:DOPBR PHA
:EMUL LDAL PCHI
 PHA
 LDAL PCLO ;put RTI stuff on user's stack
 PHA
 LDAL STATUS
 oraL Iflag ; include interrupt mask flag
 PHA
 XCE ;return to native mode
* Index may be 8 bit but that is OK.

 LDA #$FF
 STAL VIAIFR ;CLEAR OLD INTERRUPT FLAGS
 LDAL IERBUFF ;GET INTERRUPT FLAGS FROM BUFFER
 STAL VIAIER ;ENABLE INTERRUPTS

******************************************
* !!! CAUTION !!! SEGMENT DEPENDENT CODE *
******************************************

*----------------------------------------
* Alternate entry point for C0n0IO routines.
* Enter here from TOGSINT to return control to the GS interrupt handler when
* we trapped an interrupt that was not ours.
* Also used by STA/LDAINDY
* Enter with MX %10

TOC0N0IO
 LDA #%00010000 ;RAM1, ROM0
 STAL SEGMBASE,X

 MEMORY16
 LDAL XREG1
 TAX ;restore X reg
 LDAL ACC1 ;restore upper byte of Acc
 MEMORY8

 LDA #0
*********************************
* TIME CRITICAL CODE
*********************************
 STAL VIAT2CH ;FOR EXECUTION TIME, DOES NOT CAUSE NMI

 LDAL ACC1 ;load low byte with seg # for I/O transfer
 XCE ;restore emulation bit
 JMP (TOSLOTC0) ;Goto slotC0 routines

 MX %11


********************************************************************
* Save ACC & XREG to ACC1 & XREG1 in segment 1
* !!!! Alert !!!! If the stack is in DDT ram then the Acc. will not be
* saved in SEG1 ram.

AX2S1_A INDEX16
 CLC ;C=0 = Execute
 LDA ACC+1 ;hi byte
 LDX XREG
 BRA AX2S1_C

* LDA/STA entry: Save Acc & X
AX2S1_B INDEX16
 SEC ;C=1 = LDA/STA
AX2S1_C XBA ;put in HI byte
 PHY ;save Y
 PHD ;save direct reg
 TXY

* Setup SEG1 EX routine

 LDAL CNSLOT ;last active peripheral slot
 TCD ;use direct reg as temp storage

******************************************
* !!! CAUTION !!! SEGMENT DEPENDENT CODE *
******************************************
 LDA #0
 XBA
 LDA SLOTN0
 TAX
 LDA #%00010000 ;RAM1, ROM0
 STA SEGMBASE,X

 TDC ;stored in direct reg
 STA IOUSER ;setup I/O routine

 STY XREG1 ;needed to restore X

 LDA #$70 ;default to SEG 7 for part 2 of I/O
 BCC :EXEC ;if execute
 LDA #$80 ;LDA/STA continues in SEG 8	
:EXEC TAY
 STY ACC1 ;needed to restore ACC hi byte & SEG part 2

******************************************
* !!! CAUTION !!! SEGMENT DEPENDENT CODE *
******************************************
 STZ SEGMBASE,X ;RAM0, ROM0
 PLD ;restore direct reg
 PLY ;restore Y
 MX8
 RTS

*---------------------------------------------
*EXCHANGE ZERO PAGE RAM SO IT GETS UPDATED PROPERLY

EXCHZPAG PHA ;SAVE REGISTERS
 PHX
 PHY

 LDX #3 ;4 BYTES
:NEXT LDA BASBUF,X ;GET FROM DDT BUFFER
 LDY BASL,X ;GET FROM APPLE'S RAM
 STA BASL,X ;PUT IN APPLE'S RAM
 TYA
 STA BASBUF,X ;PUT IN DDT BUFFER
 DEX
 BPL :NEXT

 PLY ;RESTORE REGISTERS
 PLX
 PLA

 RTS

 MX %11 ;8 BIT

*----------------------------------------
* Restore registers for DDT operation. Used by SAVEREG & CMDDORTS

RTSREST CLC
 XCE ;native mode
 SEP #$24 ;MEMORY8 + SEI, no interrupts while in DDT

 do debug ;keep in bank 00 for APW debugger to work
 PEA #$0000
 else ;use bank #$E0 for normal operation
 PEA #$E0E0
 fin ;finish of conditional

 PLB
 PLB ;SET DATA BANK
 RTS

***********************************
* SAVE REGISTERS
* set native mode
* 5-1-91 Acc is saved before coming here.

SAVEREG PHP ;save status
 JSR RTSREST ;native mode, set DBR
 ROR EMULATE ;SET EMULATION FLAG
 PLA
 STA STATUS

 INDEX16 ;16 BIT
 STX XREG
 STY YREG
 PLX ;GET RETURN ADDRESS
 STX TEMP
 TSX
 STX STACK ;save user's stack
 BRA SAVEWSTK ;save work stack space

*----------------------------------------
* save Stack, D & set stack pointer to working area.
* enter with MX16

 MX %00
S_SAVEST = ]segnum
SAVESTK
 TSX
 STX STACK ;SAVE USER'S STACK

* Restore User's stack RAM that was disturbed by interrupt stuff.

 TXA ;CURRENT POINTER
 SEC
 SBC OLDSTACK ;CURRENT POINTER - OLD POINTER

 BIT EMULATE-1 ;WORD TEST
 BPL :NATIV
 ORA #$FF00 ;MAKE NEGATIVE
 BIT #$0080 ;TEST SIGN OF LOW BYTE
 BNE :NATIV ;IF NEG, KEEP IN SIGN EXTENDED FORM
 AND #$00FF ;8 BIT STACK SO STRIP HI BYTE
:NATIV CLC

 ADC #STACKBUF-5 ;STACK BUFFER OFFSET
 CMP #STACKBUF ;IS POINTER WITHIN LIMITS
 MEMORY8
 BGE :ENDSTKR ;IF OUTSIDE LIMITS
 TAY

 BIT EMULATE
 BPL :MODEOK ;STAY IN NATIVE MODE
 SEC
 XCE ;SET EMULATION MODE
:MODEOK TXS ;PUT BACK TO USER'S STACK

:WHILE LDA STKBUFM,Y ;GET BYTE FOR MAIN RAM STACK
 BIT ALTZP ;TEST ALTZP FLAG
 BPL :MAIN ;STACK IS IN MAIN RAM
 LDA STKBUFA,Y ;GET BYTE FOR AUX RAM STACK
:MAIN PHA
 DEY
 BPL :WHILE

 CLC
 XCE ;PUT BACK IN NATIVE MODE
 INDEX16
:ENDSTKR

*-------------------------------------------------
* Save an area of user's stack ram to ddt ram and switch stack pointer
* to this work area.
* Saves from main or aux stack ram according to setting of ALTZP
 MX %10

SAVEWSTK
 LDX #WSTKLGTH ;LENGTH OF WORK STACK

:WHILE2 LDAL WORKSTAK-WSTKLGTH,X
 STA WSTKBUFF,X ;SAVE WORK STACK TO DDT RAM
 DEX
 BNE :WHILE2

 LDX #WORKSTAK
 TXS ;SET STACK TO WORK AREA
 PHD ;PUSH 16 BIT DIRECT REG
 PLX ;PULL 16 BITS
 STX DREG ;SAVE DIRECT REG
 LDX #0000
 PHX
 PLD ;SET DIRECT REG TO INSURE IT'S IN RAM
 LDX TEMP ;GET RETURN ADDRESS
 PHX ;PUT ON STACK
 SEP #%00110100 ;8 BIT DATA & INDEX, IRQ DISABLE
 LDA ACC
 STA ZBYTE1
 RTS
 MX %11

*----------------------------------
*       INTSTUFF
*
* The DDT only traps the BRK and NMI interrupts:
* Interrupt house keeping stuff
*  Get interrupt info off user's stack.
*  Set working stack space.
*  Save registers.
*  Set native mode.
*  Enters with MEMORY8.
*  Trap only our NMI's and all BRKs but nothing else.
*
* Note! This routine must operate in the user's mode (native,emualtion) when
* dealing with the stack.

INTSTUFF
 SEI ;disable interrupts
 CLD
 STAL CXSTATUS ;save CXROM status
 PHB ;save data bank
 CLC
 XCE ;set native mode so native pulls work right
 LDA #$E0
 PHA
 PLB ;set data bank
 XCE ;restore user's mode
 XBA
 STA ACC+1 ;save hi byte

* This must be done before the capacitor on the button input recharges
* to 0.6v, approximately 0.1mS.
* Needed here incase of fast NMI
 LDA VIAPCR ;ENTER HERE TO PUT /INIT LOW
 ORA #%11101110 ;REMOVE INVISIBILITY (CA2 HI) &
* don't replace apple's vectors (CB2 HI)
***** ALLOW switching segments in DDT ROM !!! *****  (CB2 HI)
 STA VIAPCR

* Stop T2 count incase this is ET command
 LDA VIAACR
 ORA #%00100000
 STA VIAACR
*----------------------------------------------------------------------
*  !!! TIME DEPENDENT UP TO THIS POINT because of ET command
*----------------------------------------------------------------------

* get interrupt stuff off stack
 PLA
 STA DBR
 PLA
 STA ACC ;save low byte
 PLA
 STA TEMP+2 ;save post interrupt status

 PLA
 STA TEMP
 PLA
 STA TEMP+1 ;address of $3FB or $E1/0070 JSR return

 PEA INTANLYZ-1 ;address of command, Interupt Anlyze
 PEA S_INTANL ;segment # of command
 JMP JUMPSEG0 ;goto command in other segment

*-----------------------------------------------------
* Restore the work stack ram area from ddt ram buffer.
* enters with Stack set to DDTSTACK & Index16
* Restores to main or aux ram according to setting of ALTZP
 MX %10

WSTKRES
 LDX #WSTKLGTH ;LENGTH OF WORK STACK

:WHILE LDA WSTKBUFF,X ;GET WORK STACK DATA FROM DDT RAM
 STAL WORKSTAK-WSTKLGTH,X ;PUT IN STACK RAM
 DEX
 BNE :WHILE

 RTS
 MX %11

*----------------------------------------
* STACKRES
* Restore the area of the user's stack that was used by the DDT for WORK STACK
* Save User's stack
* Enters with stack in DDTSTACK
* Returns with MX16
 MX %10 ;ENTERS WITH INDEX16
STACKRES JSR WSTKRES ;RESTORE WORK STACK

*------------------------------------------
* Save the area of the user's stack that will be changed by the DDT.

STACKSAV
 INDEX16
 LDA USEROPCD ;GET USER'S OPCODE
 CMP #$9A ;IS IT TXS ?
 BNE :NOTXS ;IF NO
 LDX XREG ;USE X FOR STACK POINTER
 BRA :STACKS
:NOTXS CMP #$1B ;IS IT TCS ?
 BNE :NOTCS ;IF NO
 LDX ACC ;USE ACC FOR STACK POINTER
 BRA :STACKS

* Save the stack RAM that may be changed by the DDT interrupt.

:NOTCS LDX STACK ;GET USER'S STACK POINTER
:STACKS STX OLDSTACK ;SAVE POINTER TO BE USED DURING RESTORE
 INX
 INX
 INX ;START SAVE 4 BYTES ABOVE STACK POINTER
 INX
 LDY #STACKBUF-1 ;SAVE STACKBUF BYTES

 LDA ALTZP
 STA ALTZPBF ;SAVE ALTZP
 STA MAINZP ;SET TO MAIN RAM STACK

 CMP #$FB ;IS IT XCE ?
 BNE :NOXCE ;IF NO
 LDA STATUS
 AND #$01 ;WHAT WILL NEW MODE BE?
 BNE :EMUL ;IF 8 BIT
 BRA :SAVE16 ;IF 16 BIT

:NOXCE BIT EMULATE ;WHAT IS CURRENT MODE?
 BMI :EMUL ;CF 8 BIT

* SAVE 16 BIT STACK
* WHILE Y > 0 DO
:SAVE16 LDAL $000000,X ;GET DATA FROM MAIN STACK RAM
 STA STKBUFM,Y ;SAVE IN DDT RAM
 LDAL $010000,X ;GET DATA FROM AUX STACK RAM
 STA STKBUFA,Y ;SAVE IN DDT RAM
 DEX
 DEY
 BPL :SAVE16
* ENDW  
 BRA :ENDSTKS

:EMUL INDEX8 ;8 BIT STACK

* SAVE 8 BIT STACK
* WHILE Y > 0 DO
:WHILE LDAL $000100,X ;GET DATA FROM MAIN STACK RAM
 STA STKBUFM,Y ;SAVE IN DDT RAM
 LDAL $010100,X ;GET DATA FROM AUX STACK RAM
 STA STKBUFA,Y ;SAVE IN DDT RAM
 DEX
 DEY
 BPL :WHILE
* ENDW

:ENDSTKS
 BIT ALTZPBF ;WAS STACK IN MAIN RAM ?
 BPL :MAIN ;IF YES
 STA AUXZP ;IF NO, PUT STACK IN AUX RAM
:MAIN MX16
 RTS
 MX %11

*********************************
*  COMDJS - JSR
*********************************

* Execute the subroutine at the address following
* the "JS" command and return to DDT command prompt.

COMDJS EQU *
 BEQ TOERR0 ;IF NO ADDRESS FOLLOWS
 JSR TRANSFR0 ;check for valid hex, put in LETTER3,2,1
 DFB CHKREADC ; code
 BCC JSCONT ;if OK
TOERR0 JMP BADPAR0 ;IF bad

* Set up RTS so user's routine returns to CMDDORTS in cards I/O slot

JSCONT LDA SLOTCN  ;SLOT # $CN
 PHA   ;HI BYTE OF RETURN ADDRESS
 LDA #CMDDORTS-1 ;LOW BYTE OF RETURN ADDRESS
 PHA
 LDA LETTER1 ;LOW ADDRESS BYTE OF USER SUB
 STA SUBTRACE ;SUBTRACE IS OK TO USE
 LDA LETTER2 ;HI ADDRESS BYTE
 STA SUBTRACE+1
 JSR TRANSFR1 ;RESTORE THE Z PAGE & TEXT RAM
 DFB RESTTEXTC ;CODE
 JMP (SUBTRACE)

*----------------------------*
*  COMDRT - REAL TIME
*----------------------------*

* Run the users program in real time to the matching RTS.
* The current instruction is traced first

COMDRT LDA #$C0
 STA COMRTFLG ;INDICATE realtime active (7=1), & COMMAND RT (6=1)
 lda STATUS
 sta RTstatus ; save user's status so we can restore user's I flag
 ora #$04 ; disable interrupts for JSL
 sta STATUS

* Trace any kind of instruction with STEP1
 JMP STEP1

******************************
* COMMAND ON
******************************

S_COMDON = ]segnum ;segment number of this routine
COMDON BIT OFFFLAG ;IS DISPLAY OFF ?
 BPL ONIFON ;IF NO
 LDA #0
 STA OFFFLAG ;ENABLE DISP TO SCREEN
 JSR TRANSFR0 ;SAVE SCREEN DISPLAY IF INV ON
 DFB SAVEDISPC ;code
ONIFON JSR TRANSFR0 ;DISPLAY ALL WINDOWS
 DFB DISPONC ;code
 BRA GETCOM0

******************************
*  COMDOFF - Turn DDT display off
******************************

S_COMDOFF = ]segnum ;segment number of this routine
COMDOFF BIT OFFFLAG ;DISPLAY ALREADY OFF ?
 BMI GETCOM0 ;IF YES
 JSR TRANSFR0 ;RESTORE DISPLAY SWITCHES
 DFB RESTTEXTC ;code
 LDA #$80
 STA OFFFLAG ;DON'T DISPLAY TO SCREEN

*----------------------------------------
*   GETCOM0 - do <CR> & wait for user command
*----------------------------------------

GETCOM0 PEA GETCOMCR-1 ;address of command
 PEA S_GETCOM ;segment # of command
 JMP JUMPSEG0 ;goto command in other segment

*------------------------------------------------
***** GLOBAL SUBROUTINES IN THIS SEGMENT *****
***** MAXIMUM OF 32 *****
***** CODE BYTES ARE EQUATED AS FOLLOWS
*
* BITS 0-2 = SEGMENT NUMBER $0 THRU $7 OF SUBROUTINE
* BITS 3-7 = NUMBER OF SUBROUTINE IN SUBTABL

SUBTABL0

LDAINDYC EQU *-SUBTABL0*4+0+$100
 DA LDAINDY-1

STAINDYC EQU *-SUBTABL0*4+0+$100
 DA STAINDY-1

STEP1C EQU *-SUBTABL0*4+0+$100
 DA STEP1-1

EXECUTEC EQU *-SUBTABL0*4+0+$100
 DA EXECUTE-1

WSTKRESC EQU *-SUBTABL0*4+0+$100
 DA WSTKRES-1

AX2S1_AC EQU *-SUBTABL0*4+0+$100
 DA AX2S1_A-1

************* SEGMENT CROSSOVER AREA *************

 LST ON
S0END = $E0CF91-*
 do nolist
 LST OFF
 fin
 ERR *-1/$E0CF91
 DS $E0CF91-*,$FF

******** SAVE THE ACC, X, Y AND P REGISTERS *******
* Returns with MX = 11, saves registers

SAVEAXP0
 PHP ;SAVE STATUS
 MX16
 STX XSAVESEG ;save 16 bits
 STY YSAVESEG ;save 16 bits
 STA ASAVESEG ;save 16 bits
 MX8
 PLA ;GET STATUS
 STA PSAVESEG ;SAVE
 RTS

****** RESTORE THE ACC, X, Y AND P REGISTERS ******
* restores registers

RESTAXP0
 MEMORY8
 LDA PSAVESEG
 PHA
 MX16
 LDX XSAVESEG
 LDY YSAVESEG
 LDA ASAVESEG
 PLP

*** THIS RTS IS USED BY THE FINDSLOT ROUTINE ***
PUTSLOT RTS
 MX %11

*----------------------------------------
* Do a direct transfer to other segments

JUMPSEG0
 JSR SAVEAXP0
 LDY SLOTN0
 PLA ;pull junk byte from dest. seg
 PLA ;get destination segment
 STA SEGMBASE,Y ;the next inst' will be in new seg
 JSR RESTAXP0 ;restore after xfer from other seg
 RTS ;pull destination address from stack

* TRANSFER TO OTHER SEGMENTS
* Upper byte of X index is zeroed

TRANSFR0
 JSR SAVEAXP0
 MEMORY16
 PLA ;get return address from stack
 INC ;inc to point at code byte & for RTS
 PHA
 MEMORY8
 LDA #0 ;CURRENT SEG #
 PHA
 LDY #0
 LDA (2,S),Y ;GET CODE BYTE
 PHA ;SAVE CODE
 AND #$07 ;STRIP ALL BUT SEG #
 LDY SLOTN0
 STA SEGMBASE,Y ;NEXT INSTR. RUN FROM NEW SEGMENT
* NEW SEGMENT
 PLA ;GET CODE
 PEA RETURN0 ;where to return to
 AND #$F8 ;STIP OFF SEG# LEAVING SUB #
 LSR
 LSR ;LEAVE SUB# MULTIPLIED BY 2
* GET ADDRESS OF SUB FROM SUBTABL & PUSH ON STACK
 TAY
 MEMORY16
 LDA SUBTABL0,Y
 PHA
 BRA RESTAXP0 ;RESTORE REGISTERS, RTS TO SUBROUTINE
 MX %11

* RETURN HERE FROM SUBROUTINE

RETURN0 EQU *-1
 JSR SAVEAXP0
 PLA ;SEG # TO RETURN TO
 LDY SLOTN0
 STA SEGMBASE,Y ;RETURN TO SEGMENT
 BRA RESTAXP0

 DS \,$FF ;PUT OBJECT AT NEXT PAGE
